package com.system.manager.utils;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.system.manager.config.GeneratorProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

// 演示例子，执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
@Component
public class CodeGenerator {

    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driverClassName}")
    private String driverClassName;

    @Autowired
    private GeneratorProperties generatorProperties;


    /**
     *
     * @param module 模块名
     * @param tables 表名
     */
    public void  generator(String module, String... tables){
       for(int i = 0; i < tables.length; i++){

           String tableName = tables[i];

           // 1.构建代码生成器
           AutoGenerator mpg = new AutoGenerator();

           // 2.进行全局配置
           GlobalConfig gc = getGlobalConfig();
           mpg.setGlobalConfig(gc);

           // 3.数据源配置
           DataSourceConfig dsc = getDataSourceConfig();
           mpg.setDataSource(dsc);

           // 4.包配置
           PackageConfig pc = getPackageConfig(module);
           mpg.setPackageInfo(pc);

           // 5.自定义配置
           InjectionConfig cfg = new InjectionConfig() {
               @Override
               public void initMap() {
                   // to do nothing
               }
           };
           // 5.1如果模板引擎是 freemarker
           String templatePath = generatorProperties.getTemplatePath();
           // 如果模板引擎是 velocity
           // String templatePath = "/templates/mapper.xml.vm";

           // 自定义输出配置
           List<FileOutConfig> focList = new ArrayList<>();
           cfg.setFileOutConfigList(focList);
           // 5.2自定义输出配置
           mpg.setCfg(cfg);

           // 6.配置模板
           TemplateConfig templateConfig = new TemplateConfig();
           mpg.setTemplate(templateConfig);


           // 7.策略配置
           StrategyConfig strategy = getStrategy(tableName);
           mpg.setStrategy(strategy);

           // 8.设置模板引擎
           mpg.setTemplateEngine(new FreemarkerTemplateEngine());

           // 9进行代码生成
           mpg.execute();
       }

    }

    /**
     * 生成全局配置
     */
    public GlobalConfig getGlobalConfig(){
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        System.out.println("当前用户的根目录：" + generatorProperties.getProjectPath());
        // 获取用户的根目录
        String projectPath = System.getProperty(generatorProperties.getProjectPath());
        // 所生成的文件会在/src/main/java目录下
        gc.setOutputDir(projectPath + generatorProperties.getOutputDir());
        // 设置作者的名字
        gc.setAuthor("yxp");
        gc.setOpen(false);
        gc.setSwagger2(true);  // 实体属性 Swagger2 注解
        // 设置ID属性为自增
//        gc.setIdType(IdType.AUTO);
        // 设置日期的格式
        gc.setDateType(DateType.ONLY_DATE);
        // 设置service层的名字
//        gc.setServiceName("%sService"); // 去掉service的I前缀
//        gc.setMapperName("%sDao");

        return gc;
    }

    /**
     * 数据源配置
     */
    public DataSourceConfig getDataSourceConfig(){
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(dbUrl);
        // dsc.setSchemaName("public");
        dsc.setDriverName(driverClassName);
        dsc.setUsername(username);
        dsc.setPassword(password);

        return dsc;
    }

    /**
     * 包配置
     */
    public PackageConfig getPackageConfig(String module){
        // 包配置
        PackageConfig pc = new PackageConfig();

        // 设置所有模块的父包名
        pc.setParent(generatorProperties.getParentPackage());
//        pc.setEntity("entity");
//        pc.setMapper("mapper");
//        pc.setService("service");
//        pc.setController("controller");
        // 设置模块名
        pc.setModuleName(module);

        return pc;
    }
    /**
     * 根据策略制定对应生成对象
     * @return
     */
    public StrategyConfig getStrategy(String tableName){
        StrategyConfig strategy = new StrategyConfig();

        // 下划线转驼峰命名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);

        // entity类使用lombok
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);

        // 设置要映射的表名
        strategy.setInclude(tableName);

        // 设置逻辑删除的字段
        strategy.setLogicDeleteFieldName("deleted");

        // 设置自动填充配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        List<TableFill> fills = new ArrayList<>();
        fills.add(createTime);
        fills.add(updateTime);
        strategy.setTableFillList(fills);

        strategy.setControllerMappingHyphenStyle(true);
//        strategy.setTablePrefix("t_");

        return strategy;
    }

    /**
     * 代码生成器,生成单个模块、单个表
     */
    public void generator(){
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        // 获取用户的根目录
        String projectPath = System.getProperty("user.dir");
        // 所生成的文件会在/src/main/java目录下
        gc.setOutputDir(projectPath + "/src/main/java");
        // 设置作者的名字
        gc.setAuthor("yxp");
        gc.setOpen(false);
        gc.setSwagger2(true);  // 实体属性 Swagger2 注解
        // 设置ID属性为自增
//        gc.setIdType(IdType.AUTO);
        // 设置日期的格式
        gc.setDateType(DateType.ONLY_DATE);
        // 设置service层的名字
        gc.setServiceName("%sService"); // 去掉service的I前缀
        gc.setMapperName("%sDao");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://rm-bp1k374xl0x6v67pago.mysql.rds.aliyuncs.com:3306/sys_mannager?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("Yp001001");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        // 设置模块名字
        pc.setParent("com.system.manager.modules");
//        pc.setEntity("entity");
//        pc.setMapper("mapper");
//        pc.setService("service");
//        pc.setController("controller");
        pc.setModuleName("authorized");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
//        focList.add(new FileOutConfig(templatePath) {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
//                return projectPath + "/src/main/resources/mapper/modules/*/mapper/xml/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
//            }
//        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录，自定义目录用");
                if (fileType == FileType.MAPPER) {
                    // 已经生成 mapper 文件判断存在，不想重新生成返回 false
                    return !new File(filePath).exists();
                }
                // 允许生成模板文件
                return true;
            }
        });
        */
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径，注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

//        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        // 下划线转驼峰命名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // entity类使用lombok
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 设置要映射的表名
        strategy.setInclude("system_menu");

        // 设置逻辑删除的字段
        strategy.setLogicDeleteFieldName("deleted");
        // 设置自动填充配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        List<TableFill> fills = new ArrayList<>();
        fills.add(createTime);
        fills.add(updateTime);
        strategy.setTableFillList(fills);

        strategy.setControllerMappingHyphenStyle(true);
//        strategy.setTablePrefix("t_");

        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

    public static void main(String[] args) {
        CodeGenerator generator = new CodeGenerator();
        generator.generator("authorized", "user", "role");

    }

}